//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.jxls.transform.poi;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jxls.common.*;
import org.jxls.transform.AbstractTransformer;
import org.jxls.util.CannotOpenWorkbookException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class PoiTransformer extends AbstractTransformer {
    public static final String POI_CONTEXT_KEY = "util";
    private static Logger logger = LoggerFactory.getLogger(PoiTransformer.class);
    private Workbook workbook;
    private OutputStream outputStream;
    private InputStream inputStream;
    private final boolean isSXSSF;
    private ExceptionHandler exceptionHandler;
    private CellStyle cellStyle;

    private PoiTransformer(Workbook workbook) {
        this(workbook, false);
    }

    public PoiTransformer(Workbook workbook, boolean streaming) {
        this(workbook, streaming, 100, false, false);
    }

    public PoiTransformer(Workbook workbook, boolean streaming, int rowAccessWindowSize, boolean compressTmpFiles, boolean useSharedStringsTable) {
        this.exceptionHandler = new PoiExceptionLogger();
        this.workbook = workbook;
        this.isSXSSF = streaming;
        this.readCellData();
//        if (this.isSXSSF) {
//            if (!(this.workbook instanceof XSSFWorkbook)) {
//                throw new IllegalArgumentException("Failed to create POI Transformer using SXSSF API as the input workbook is not XSSFWorkbook");
//            }
//
//            this.workbook = new SXSSFWorkbook((XSSFWorkbook)this.workbook, rowAccessWindowSize, compressTmpFiles, useSharedStringsTable);
//        }

    }

    protected boolean isStreaming() {
        return this.isSXSSF;
    }

    public void setInputStream(InputStream is) {
        this.inputStream = is;
    }

    public static PoiTransformer createTransformer(InputStream is, OutputStream os) {
        PoiTransformer transformer = createTransformer(is);
        transformer.setOutputStream(os);
        transformer.setInputStream(is);
        return transformer;
    }

    public static PoiTransformer createTransformer(InputStream is) {
        Workbook workbook;
        try {
            workbook = WorkbookFactory.create(is);
        } catch (Exception var3) {
            throw new CannotOpenWorkbookException(var3);
        }

        return createTransformer(workbook);
    }

    public static PoiTransformer createTransformer(Workbook workbook) {
        return new PoiTransformer(workbook);
    }

    public static PoiTransformer createSxssfTransformer(Workbook workbook) {
        return createSxssfTransformer(workbook, 100, false);
    }

    public static PoiTransformer createSxssfTransformer(Workbook workbook, int rowAccessWindowSize, boolean compressTmpFiles) {
        return createSxssfTransformer(workbook, rowAccessWindowSize, compressTmpFiles, false);
    }

    public static PoiTransformer createSxssfTransformer(Workbook workbook, int rowAccessWindowSize, boolean compressTmpFiles, boolean useSharedStringsTable) {
        return new PoiTransformer(workbook, true, rowAccessWindowSize, compressTmpFiles, useSharedStringsTable);
    }

    public static Context createInitialContext() {
        Context context = new Context();
        context.putVar("util", new PoiUtil());
        return context;
    }

    public boolean isForwardOnly() {
        return this.isStreaming();
    }

    public Workbook getWorkbook() {
        return this.workbook;
    }

    private void readCellData() {
        int numberOfSheets = this.workbook.getNumberOfSheets();

        for(int i = 0; i < numberOfSheets; ++i) {
            Sheet sheet = this.workbook.getSheetAt(i);
            SheetData sheetData = PoiSheetData.createSheetData(sheet, this);
            this.sheetMap.put(sheetData.getSheetName(), sheetData);
        }

    }

    public void transform(CellRef srcCellRef, CellRef targetCellRef, Context context, boolean updateRowHeightFlag) {
        CellData cellData = this.isTransformable(srcCellRef, targetCellRef);
        if (cellData != null) {
            Sheet destSheet = this.workbook.getSheet(targetCellRef.getSheetName());
            if (destSheet == null) {
                destSheet = this.workbook.createSheet(targetCellRef.getSheetName());
                PoiUtil.copySheetProperties(this.workbook.getSheet(srcCellRef.getSheetName()), destSheet);
            }

            Row destRow = destSheet.getRow(targetCellRef.getRow());
            if (destRow == null) {
                destRow = destSheet.createRow(targetCellRef.getRow());
            }

            this.transformCell(srcCellRef, targetCellRef, context, updateRowHeightFlag, cellData, destSheet, destRow);
        }
    }

    protected CellData isTransformable(CellRef srcCellRef, CellRef targetCellRef) {
        CellData cellData = this.getCellData(srcCellRef);
        if (cellData == null || targetCellRef != null && targetCellRef.getSheetName() != null) {
            return cellData;
        } else {
            logger.info("Target cellRef is null or has empty sheet name, cellRef=" + targetCellRef);
            return null;
        }
    }

    protected void transformCell(CellRef srcCellRef, CellRef targetCellRef, Context context, boolean updateRowHeightFlag, CellData cellData, Sheet destSheet, Row destRow) {
        SheetData sheetData = (SheetData)this.sheetMap.get(srcCellRef.getSheetName());
        if (!this.isIgnoreColumnProps()) {
            destSheet.setColumnWidth(targetCellRef.getCol(), sheetData.getColumnWidth(srcCellRef.getCol()));
        }

        if (updateRowHeightFlag && !this.isIgnoreRowProps()) {
            destRow.setHeight((short)sheetData.getRowData(srcCellRef.getRow()).getHeight());
        }

        Cell destCell = destRow.getCell(targetCellRef.getCol());
        if (destCell == null) {
            destCell = destRow.createCell(targetCellRef.getCol());
        }

        try {
            destCell.setCellValue("");
            ((PoiCellData)cellData).writeToCell(destCell, context, this);
            this.copyMergedRegions(cellData, targetCellRef);
        } catch (Exception var11) {
            this.getExceptionHandler().handleCellException(var11, cellData.toString(), context.toMap().keySet().toString());
        }

    }

    public ExceptionHandler getExceptionHandler() {
        return this.exceptionHandler;
    }

    public void setExceptionHandler(ExceptionHandler exceptionHandler) {
        if (exceptionHandler == null) {
            throw new IllegalArgumentException();
        } else {
            this.exceptionHandler = exceptionHandler;
        }
    }

    public void resetArea(AreaRef areaRef) {
        this.removeMergedRegions(areaRef);
        this.removeConditionalFormatting(areaRef);
    }

    private void removeMergedRegions(AreaRef areaRef) {
        Sheet destSheet = this.workbook.getSheet(areaRef.getSheetName());
        int numMergedRegions = destSheet.getNumMergedRegions();

        for(int i = numMergedRegions; i > 0; --i) {
            destSheet.removeMergedRegion(i - 1);
        }

    }

    private void removeConditionalFormatting(AreaRef areaRef) {
        Sheet destSheet = this.workbook.getSheet(areaRef.getSheetName());
        CellRangeAddress areaRange = CellRangeAddress.valueOf(areaRef.toString());
        SheetConditionalFormatting sheetConditionalFormatting = destSheet.getSheetConditionalFormatting();
        int numConditionalFormattings = sheetConditionalFormatting.getNumConditionalFormattings();

        for(int index = 0; index < numConditionalFormattings; ++index) {
            ConditionalFormatting conditionalFormatting = sheetConditionalFormatting.getConditionalFormattingAt(index);
            CellRangeAddress[] ranges = conditionalFormatting.getFormattingRanges();
            List<CellRangeAddress> newRanges = new ArrayList();
            CellRangeAddress[] var10 = ranges;
            int var11 = ranges.length;

            for(int var12 = 0; var12 < var11; ++var12) {
                CellRangeAddress range = var10[var12];
                if (!areaRange.isInRange(range.getFirstRow(), range.getFirstColumn()) || !areaRange.isInRange(range.getLastRow(), range.getLastColumn())) {
                    newRanges.add(range);
                }
            }

//            conditionalFormatting.setFormattingRanges((CellRangeAddress[])newRanges.toArray(new CellRangeAddress[0]));
        }

    }

    protected final void copyMergedRegions(CellData sourceCellData, CellRef destCell) {
        if (sourceCellData.getSheetName() == null) {
            throw new IllegalArgumentException("Sheet name is null in copyMergedRegions");
        } else {
            PoiSheetData sheetData = (PoiSheetData)this.sheetMap.get(sourceCellData.getSheetName());
            CellRangeAddress cellMergedRegion = null;
            Iterator var5 = sheetData.getMergedRegions().iterator();

            while(var5.hasNext()) {
                CellRangeAddress mergedRegion = (CellRangeAddress)var5.next();
                if (mergedRegion.getFirstRow() == sourceCellData.getRow() && mergedRegion.getFirstColumn() == sourceCellData.getCol()) {
                    cellMergedRegion = mergedRegion;
                    break;
                }
            }

            if (cellMergedRegion != null) {
                this.findAndRemoveExistingCellRegion(destCell);
                Sheet destSheet = this.workbook.getSheet(destCell.getSheetName());
                destSheet.addMergedRegion(new CellRangeAddress(destCell.getRow(), destCell.getRow() + cellMergedRegion.getLastRow() - cellMergedRegion.getFirstRow(), destCell.getCol(), destCell.getCol() + cellMergedRegion.getLastColumn() - cellMergedRegion.getFirstColumn()));
            }

        }
    }

    protected final void findAndRemoveExistingCellRegion(CellRef cellRef) {
        Sheet destSheet = this.workbook.getSheet(cellRef.getSheetName());
        int numMergedRegions = destSheet.getNumMergedRegions();

        for(int i = 0; i < numMergedRegions; ++i) {
            CellRangeAddress mergedRegion = destSheet.getMergedRegion(i);
            if (mergedRegion.getFirstRow() <= cellRef.getRow() && mergedRegion.getLastRow() >= cellRef.getRow() && mergedRegion.getFirstColumn() <= cellRef.getCol() && mergedRegion.getLastColumn() >= cellRef.getCol()) {
                destSheet.removeMergedRegion(i);
                break;
            }
        }

    }

    public void setFormula(CellRef cellRef, String formulaString) {
        if (cellRef != null && cellRef.getSheetName() != null) {
            Sheet sheet = this.workbook.getSheet(cellRef.getSheetName());
            if (sheet == null) {
                sheet = this.workbook.createSheet(cellRef.getSheetName());
            }

            Row row = sheet.getRow(cellRef.getRow());
            if (row == null) {
                row = sheet.createRow(cellRef.getRow());
            }

            Cell poiCell = row.getCell(cellRef.getCol());
            if (poiCell == null) {
                poiCell = row.createCell(cellRef.getCol());
            }

            try {
                poiCell.setCellFormula(formulaString);
                this.clearCellValue(poiCell);
            } catch (Exception var7) {
                this.getExceptionHandler().handleFormulaException(var7, cellRef.getCellName(), formulaString);
            }

        }
    }

    protected void clearCellValue(Cell poiCell) {
        if (poiCell instanceof XSSFCell) {
            CTCell cell = ((XSSFCell)poiCell).getCTCell();
            if (cell.isSetV()) {
                cell.unsetV();
            }
        }

    }

    public void clearCell(CellRef cellRef) {
        if (cellRef != null && cellRef.getSheetName() != null) {
            Sheet sheet = this.workbook.getSheet(cellRef.getSheetName());
            if (sheet != null) {
                this.removeCellComment(sheet, cellRef.getRow(), cellRef.getCol());
                Row row = this.getRowForClearCell(sheet, cellRef);
                if (row != null) {
                    Cell cell = row.getCell(cellRef.getCol());
                    if (cell == null) {
//                        CellAddress cellAddress = new CellAddress(cellRef.getRow(), cellRef.getCol());
//                        if (sheet.getCellComment(cellAddress) != null) {
//                            cell = row.createCell(cellRef.getCol());
//                            cell.removeCellComment();
//                        }

                    } else {
//                        cell.setBlank();
                        cell.setCellValue("");
                        cell.setCellStyle(this.workbook.getCellStyleAt((short) 0));
                        if (cell.getCellComment() != null) {
                            cell.removeCellComment();
                        }

                        this.findAndRemoveExistingCellRegion(cellRef);
                    }
                }
            }
        }
    }

    protected Row getRowForClearCell(Sheet sheet, CellRef cellRef) {
        return sheet.getRow(cellRef.getRow());
    }

    protected final void removeCellComment(Sheet sheet, int rowNum, int colNum) {
        Row row = sheet.getRow(rowNum);
        if (row != null) {
            Cell cell = row.getCell(colNum);
            if (cell != null) {
                cell.removeCellComment();
            }
        }
    }

    public List<CellData> getCommentedCells() {
        List<CellData> commentedCells = new ArrayList();
        Iterator var2 = this.sheetMap.values().iterator();

        while(var2.hasNext()) {
            SheetData sheetData = (SheetData)var2.next();
            Iterator var4 = sheetData.iterator();

            while(var4.hasNext()) {
                RowData rowData = (RowData)var4.next();
                if (rowData != null) {
                    int row = ((PoiRowData)rowData).getRow().getRowNum();
                    List<CellData> cellDataList = this.readCommentsFromSheet(((PoiSheetData)sheetData).getSheet(), row);
                    commentedCells.addAll(cellDataList);
                    return commentedCells;
                }
            }
        }

        return commentedCells;
    }

    private void addImage(AreaRef areaRef, int imageIdx, Double scaleX, Double scaleY) {
//        boolean pictureResizeFlag = scaleX != null && scaleY != null;
//        CreationHelper helper = this.workbook.getCreationHelper();
//        Sheet sheet = this.workbook.getSheet(areaRef.getSheetName());
//        if (sheet == null) {
//            sheet = this.workbook.createSheet(areaRef.getSheetName());
//        }
//
//        Drawing<?> drawing = sheet.createDrawingPatriarch();
//        ClientAnchor anchor = helper.createClientAnchor();
//        anchor.setCol1(areaRef.getFirstCellRef().getCol());
//        anchor.setRow1(areaRef.getFirstCellRef().getRow());
//        if (pictureResizeFlag) {
//            anchor.setAnchorType(AnchorType.MOVE_DONT_RESIZE);
//            anchor.setCol2(-1);
//            anchor.setRow2(-1);
//        } else {
//            anchor.setCol2(areaRef.getLastCellRef().getCol());
//            anchor.setRow2(areaRef.getLastCellRef().getRow());
//        }
//
//        Picture picture = drawing.createPicture(anchor, imageIdx);
//        if (pictureResizeFlag) {
//            picture.resize(scaleX, scaleY);
//        }

    }

    public void addImage(AreaRef areaRef, byte[] imageBytes, ImageType imageType, Double scaleX, Double scaleY) {
        int poiPictureType = this.findPoiPictureTypeByImageType(imageType);
        int pictureIdx = this.workbook.addPicture(imageBytes, poiPictureType);
        this.addImage(areaRef, pictureIdx, scaleX, scaleY);
    }

    public void addImage(AreaRef areaRef, byte[] imageBytes, ImageType imageType) {
        int poiPictureType = this.findPoiPictureTypeByImageType(imageType);
        int pictureIdx = this.workbook.addPicture(imageBytes, poiPictureType);
        this.addImage(areaRef, pictureIdx, (Double)null, (Double)null);
    }

    public void write() throws IOException {
        this.writeButNotCloseStream();
        this.outputStream.close();
        this.dispose();
    }

    public void writeButNotCloseStream() throws IOException {
        if (this.outputStream == null) {
            throw new IllegalStateException("Cannot write a workbook with an uninitialized output stream");
        } else if (this.workbook == null) {
            throw new IllegalStateException("Cannot write an uninitialized workbook");
        } else {
            if (!this.isStreaming() && this.isEvaluateFormulas()) {
                this.workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();
            }

            if (this.isFullFormulaRecalculationOnOpening()) {
                this.workbook.setForceFormulaRecalculation(true);
            }

            this.workbook.write(this.outputStream);
        }
    }

    public void dispose() {
        try {
            if (this.workbook instanceof SXSSFWorkbook) {
                ((SXSSFWorkbook)this.workbook).dispose();
            }
        } catch (Exception var2) {
            logger.warn("Error disposing streamed workbook", var2);
        }

    }

    private int findPoiPictureTypeByImageType(ImageType imageType) {
        int poiType = -1;
        if (imageType == null) {
            throw new IllegalArgumentException("Image type is undefined");
        } else {
            switch(imageType) {
                case PNG:
                    poiType = 6;
                    break;
                case JPEG:
                    poiType = 5;
                    break;
                case EMF:
                    poiType = 2;
                    break;
                case WMF:
                    poiType = 3;
                    break;
                case DIB:
                    poiType = 7;
                    break;
                case PICT:
                    poiType = 4;
            }

            return poiType;
        }
    }

    private List<CellData> readCommentsFromSheet(Sheet sheet, int rowNum) {
        List<CellData> commentDataCells = new ArrayList();

        for (Row row : sheet) {
            for (Cell cell : row) {
                Comment comment = cell.getCellComment();
                if (comment != null) {
                    if (comment.getString() != null) {
                        CellData cellData = new CellData(new CellRef(sheet.getSheetName(), cell.getRowIndex(), cell.getColumnIndex()));
                        cellData.setCellComment(comment.getString().getString());
                        commentDataCells.add(cellData);
                    }
                }
            }
        }
        commentDataCells.sort((a, b) -> {
            return a.getCol() - b.getCol();
        });
        return commentDataCells;
    }

    public OutputStream getOutputStream() {
        return this.outputStream;
    }

    public void setOutputStream(OutputStream outputStream) {
        this.outputStream = outputStream;
    }

    public InputStream getInputStream() {
        return this.inputStream;
    }

    public CellStyle getCellStyle(CellRef cellRef) {
        SheetData sheetData = (SheetData)this.sheetMap.get(cellRef.getSheetName());
        PoiCellData cellData = (PoiCellData)sheetData.getRowData(cellRef.getRow()).getCellData(cellRef.getCol());
        return cellData.getCellStyle();
    }

    public boolean deleteSheet(String sheetName) {
        if (super.deleteSheet(sheetName)) {
            int sheetIndex = this.workbook.getSheetIndex(sheetName);
            this.workbook.removeSheetAt(sheetIndex);
            return true;
        } else {
            logger.warn("Failed to find '{}' worksheet in a sheet map. Skipping the deletion.", sheetName);
            return false;
        }
    }

    public void setHidden(String sheetName, boolean hidden) {
        int sheetIndex = this.workbook.getSheetIndex(sheetName);
        this.workbook.setSheetHidden(sheetIndex, hidden);
    }

    public void updateRowHeight(String srcSheetName, int srcRowNum, String targetSheetName, int targetRowNum) {
        if (!this.isSXSSF) {
            SheetData sheetData = (SheetData)this.sheetMap.get(srcSheetName);
            RowData rowData = sheetData.getRowData(srcRowNum);
            Sheet sheet = this.workbook.getSheet(targetSheetName);
            if (sheet == null) {
                sheet = this.workbook.createSheet(targetSheetName);
            }

            Row targetRow = sheet.getRow(targetRowNum);
            if (targetRow == null) {
                targetRow = sheet.createRow(targetRowNum);
            }

            short srcHeight = rowData != null ? (short)rowData.getHeight() : sheet.getDefaultRowHeight();
            targetRow.setHeight(srcHeight);
        }
    }

    public XSSFWorkbook getXSSFWorkbook() {
        if (this.workbook instanceof SXSSFWorkbook) {
            return ((SXSSFWorkbook)this.workbook).getXSSFWorkbook();
        } else {
            return this.workbook instanceof XSSFWorkbook ? (XSSFWorkbook)this.workbook : null;
        }
    }

    public void adjustTableSize(CellRef ref, Size size) {
        XSSFWorkbook xwb = this.getXSSFWorkbook();
        if (size.getHeight() > 0 && xwb != null) {
            XSSFSheet sheet = xwb.getSheet(ref.getSheetName());
            if (sheet == null) {
                logger.error("Can not access sheet '{}'", ref.getSheetName());
            } else {
                Iterator var5 = sheet.getTables().iterator();

                while(var5.hasNext()) {
                    XSSFTable table = (XSSFTable)var5.next();
//                    AreaRef areaRef = new AreaRef(table.getSheetName() + "!" + table.getCTTable().getRef());
//                    if (areaRef.contains(ref)) {
//                        areaRef.getLastCellRef().setRow(ref.getRow() + size.getHeight() - 1);
//                        table.getCTTable().setRef(areaRef.getFirstCellRef().toString(true) + ":" + areaRef.getLastCellRef().toString(true));
//                    }
                }
            }
        }

    }

    public void mergeCells(CellRef cellRef, int rows, int cols) {
        Sheet sheet = this.getWorkbook().getSheet(cellRef.getSheetName());
        CellRangeAddress region = new CellRangeAddress(cellRef.getRow(), cellRef.getRow() + rows - 1, cellRef.getCol(), cellRef.getCol() + cols - 1);
        sheet.addMergedRegion(region);

        try {
            this.cellStyle = this.getCellStyle(cellRef);
        } catch (Exception var10) {
        }

        for(int i = region.getFirstRow(); i <= region.getLastRow(); ++i) {
            Row row = sheet.getRow(i);
            if (row == null) {
                row = sheet.createRow(i);
            }

            for(int j = region.getFirstColumn(); j <= region.getLastColumn(); ++j) {
                Cell cell = row.getCell(j);
                if (cell == null) {
                    cell = row.createCell(j);
                }

                if (this.cellStyle == null) {
//                    cell.getCellStyle().setAlignment(HorizontalAlignment.CENTER);
                    cell.getCellStyle().setAlignment(CellStyle.ALIGN_CENTER);
                    cell.getCellStyle().setVerticalAlignment(CellStyle.VERTICAL_CENTER);
                } else {
                    cell.setCellStyle(this.cellStyle);
                }
            }
        }

    }
}
